module groupManager (
    input wire clk,
    input wire rst,
    input wire ram_idle_1,                          //组内RAM1的状态
    input wire ram_idle_2,                          //组内RAM2的状态
    input wire ram_idle_3,                          //组内RAM3的状态
    input wire ram_idle_4,                          //组内RAM4的状态
    input wire write_en_1,                  //�˿�2��дʹ��
    input wire [5:0] data_priority_1,       //�˿�1�����ݵ����ȼ�
    input wire [9:0] data_size_1,
    input wire [15:0] data_target_port_1,
    input wire write_en_2,                  //�˿�2��дʹ��
    input wire [5:0] data_priority_2,       //�˿�2�����ݵ����ȼ�
    input wire [9:0] data_size_2,
    input wire [15:0] data_target_port_2,
    input wire write_en_3,                  //�˿�3��дʹ��
    input wire [5:0] data_priority_3,       //�˿�3�����ݵ����ȼ�
    input wire [9:0] data_size_3,
    input wire [15:0] data_target_port_3,
    input wire write_en_4,                  //�˿�4��дʹ��
    input wire [5:0] data_priority_4,       //�˿�4�����ݵ����ȼ�
    input wire [9:0] data_size_4,
    input wire [15:0] data_target_port_4,
    input wire [3:0] data_ready_in,
    input wire [31:0] data_in [0:3],
    output reg [3:0] data_ready_out,
    output reg [31:0] data_out [0:3],
    output reg write_en_out,                        //组管理器的写使能输出                 
    output reg [5:0] write_priority_out,            //组管理器的写优先级输出
    output reg [9:0] write_size_out,                //组管理器的数据包长度输出
    output reg [15:0] write_port_out,                //组管理器的目的端口输出
    output reg [3:0] pick_ram,                      //最终选中的工作端口
    output reg [3:0] write_arbitration              //组管理器的端口仲裁结果
);  
    integer i;
    wire [3:0] arbitration;
    wire [3:0] ram_state, ram_sel;
    reg [1:0] work_state [0:3];
    reg [3:0] history_port [0:3];

    assign ram_state = {ram_idle_4, ram_idle_3, ram_idle_2, ram_idle_1};

    always @(posedge clk) begin
        if (write_arbitration == 4'b0001) begin
            write_en_out <= write_en_1;
            write_priority_out <= data_priority_1;
            write_size_out <= data_size_1;
            write_port_out <= data_target_port_1;
        end

        if (write_arbitration == 4'b0010) begin
            write_en_out <= write_en_2;
            write_priority_out <= data_priority_2;
            write_size_out <= data_size_2;
            write_port_out <= data_target_port_2;
        end

        if (write_arbitration == 4'b0100) begin
            write_en_out <= write_en_3;
            write_priority_out <= data_priority_3;
            write_size_out <= data_size_3;
            write_port_out <= data_target_port_3;
        end

        if (write_arbitration == 4'b1000) begin
            write_en_out <= write_en_4;
            write_priority_out <= data_priority_4;
            write_size_out <= data_size_4;
            write_port_out <= data_target_port_4;
        end

        if (write_arbitration == 4'b0000) begin
            write_en_out <= 1'b0;
        end
    end

    always @(posedge clk) begin
        if (rst) begin
            data_ready_out <= 4'b0000;
            for (i=0; i<4; i=i+1) begin
                data_out[i] <= 0;
                work_state[i] <= 2'b00;
            end
        end
        else begin
            write_arbitration <= arbitration;
            pick_ram <= ram_sel;

            for (i=0; i<4; i=i+1) begin
                if (work_state[i]==2'b00) begin
                    if (ram_sel[i]==4'b0001 && arbitration>0) begin
                        history_port[i] <= arbitration;
                        work_state[i] <= 2'b01;
                    end

                    if (ram_sel[i]==4'b0010 && arbitration>0) begin
                        history_port[i] <= arbitration;
                        work_state[i] <= 2'b01;
                    end

                    if (ram_sel[i]==4'b0100 && arbitration>0) begin
                        history_port[i] <= arbitration;
                        work_state[i] <= 2'b01;
                    end

                    if (ram_sel[i]==4'b1000 && arbitration>0) begin
                        history_port[i] <= arbitration;
                        work_state[i] <= 2'b01;
                    end
                end

                if (work_state[i]==2'b10) begin
                    if ((data_ready_in&history_port[i])>0) begin
                        data_ready_out[i] <= 1'b1;
                        if (history_port[i]==4'b0001) begin
                            data_out[i] <= data_in[0];
                        end

                        if (history_port[i]==4'b0010) begin
                            data_out[i] <= data_in[1];
                        end

                        if (history_port[i]==4'b0100) begin
                            data_out[i] <= data_in[2];
                        end

                        if (history_port[i]==4'b1000) begin
                            data_out[i] <= data_in[3];
                        end
                    end

                    if ((data_ready_in&history_port[i])==0) begin
                        data_ready_out[i] <= 1'b0;
                        data_out[i] <= 0;
                        work_state[i] <= 2'b00;
                        history_port[i] <= 0;
                    end
                end

                if (work_state[i]==2'b01) begin
                    if ((data_ready_in&history_port[i])>0) begin
                        work_state[i] <= 2'b10;
                        data_ready_out[i] <= 1'b1;
                        if (history_port[i]==4'b0001) begin
                            data_out[i] <= data_in[0];
                        end

                        if (history_port[i]==4'b0010) begin
                            data_out[i] <= data_in[1];
                        end

                        if (history_port[i]==4'b0100) begin
                            data_out[i] <= data_in[2];
                        end

                        if (history_port[i]==4'b1000) begin
                            data_out[i] <= data_in[3];
                        end
                    end
                end
            end
        end
    end


    idleRamPicker ramPicker(.ram_idle(ram_state), .pick_ram(ram_sel));
    
    priorityArbiter4 arb(.write_en_1(write_en_1), .priority_1(data_priority_1), .write_en_2(write_en_2), .priority_2(data_priority_2), .write_en_3(write_en_3), .priority_3(data_priority_3), .write_en_4(write_en_4), .priority_4(data_priority_4), .priority_arbitration(arbitration));
endmodule